package com.xhwl.data.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.common.dto.cent.sdata.AccountPersonalDTO;
import com.xhwl.common.dto.cent.sdata.AdminAccountDTO;
import com.xhwl.common.enums.AppTypeEnum;
import com.xhwl.common.enums.CodeEnum;
import com.xhwl.common.enums.PasswordEditEnum;
import com.xhwl.common.enums.sdata.DevelopStatusEnum;
import com.xhwl.common.exception.DataException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.sdata.*;
import com.xhwl.common.pojo.cent.sdata.devplatform.Developer;
import com.xhwl.common.pojo.cent.vehicle.bo.bi.query.QueryVehicleTotalStatisticsBO;
import com.xhwl.common.query.cent.sdata.AccountQuery;
import com.xhwl.common.utils.CentDataVerifyUtil;
import com.xhwl.common.utils.DateUtils;
import com.xhwl.data.pojo.vo.AdminAccountVO;
import com.xhwl.data.service.*;
import com.xhwl.data.service.devplatform.IDeveloperService;
import com.xhwl.data.util.Constant;
import com.xhwl.data.util.RedisUtils;
import com.xhwl.data.util.ValidatorUtil;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.MyBatisSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.security.auth.login.AccountExpiredException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author: luyi
 * @Description:
 * @Date: Create in 18:27 2022/6/29
 */
@RestController
public class AdminAccountController {

    @Autowired
    private IAdminAccountService adminAccountService;

    @Autowired
    private IAdminAccountRoleService adminAccountRoleService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    IMessageCodeService messageCodeService;

    @Autowired
    IAccountService accountService;

    @Autowired
    IDeveloperService developerService;

    @Autowired
    private RedisTemplate redisTemplate;

    private static final Logger log = LoggerFactory.getLogger(AdminAccountController.class);

    @PostMapping("/admin-account/create")
    public ResultJson create(@RequestBody AdminAccountDTO adminAccountDTO, AdminAccount adminAccount, App app){
        adminAccountDTO.setDevelopId(app.getDevelopId());
        if(null != adminAccountDTO.getId()){
            return adminAccountService.update(adminAccountDTO);
        }else{
            adminAccountDTO.setIndustryId(app.getIndustryId());
            return adminAccountService.create(adminAccountDTO);
        }
    }

    /**
     * 后台帐号分页查询
     * @param adminAccountVO
     * @param app
     * @return
     */
    @PostMapping("/admin-account/page")
    public ResultJson page(@RequestBody AdminAccountVO adminAccountVO, App app){

        adminAccountVO.getAdminAccountQuery().setDevelopId(app.getDevelopId());
        Page page = adminAccountService.page(adminAccountVO.getAdminAccountQuery(), adminAccountVO.getPage());
        List<AdminAccount> records = page.getRecords();
        if(!CollectionUtils.isEmpty(records)){
            List<Integer> collect = records.stream().map(i -> i.getId()).collect(Collectors.toList());
            QueryWrapper<AdminAccountRole> adminAccountRoleQueryWrapper = new QueryWrapper<>();
            adminAccountRoleQueryWrapper.in("admin_account_id", collect);
            List<AdminAccountRole> list = adminAccountRoleService.list(adminAccountRoleQueryWrapper);
            Map<Integer, List<Integer>> collect1 = list.stream().collect(Collectors.groupingBy(AdminAccountRole::getAdminAccountId, Collectors.mapping(i -> i.getRoleId(), Collectors.toList())));
            List<Integer> roleIds = list.stream().map(i -> i.getRoleId()).distinct().collect(Collectors.toList());
            Map<Integer, String> roleMap = new HashMap<>();
            if(!CollectionUtils.isEmpty(roleIds)){
                QueryWrapper<Role> roleQueryWrapper = new QueryWrapper<>();
                roleQueryWrapper.select("id", "name");
                roleQueryWrapper.in("id", roleIds);
                List<Role> list1 = roleService.list(roleQueryWrapper);
                roleMap = list1.stream().collect(Collectors.toMap(Role::getId, Role::getName));
            }


            List<AdminAccountDTO> adminAccountDTOS = new ArrayList<>(records.size());
            for (AdminAccount record : records) {
                AdminAccountDTO adminAccountDTO = new AdminAccountDTO();
                BeanUtils.copyProperties(record, adminAccountDTO);
                List<Integer> integers = collect1.get(record.getId());
                if(!CollectionUtils.isEmpty(integers)){
                    adminAccountDTO.setRoleIds(integers);
                    List<String> roleName = new ArrayList<>();
                    for (Integer integer : integers) {
                        String s = roleMap.get(integer);
                        roleName.add(s);
                    }
                    adminAccountDTO.setRoleNames(roleName);
                }
                adminAccountDTOS.add(adminAccountDTO);
            }
            page.setRecords(adminAccountDTOS);
        }
        return ResultJson.success(page);
    }

    @PostMapping("/admin-account/remove-role")
    public ResultJson removeRole(@RequestBody AdminAccountRole adminAccountRole){

        AdminAccount admin = adminAccountService.getById(adminAccountRole.getAdminAccountId());
        if(null == admin){
            return ResultJson.fail("帐号不存在");
        }
        if(null != adminAccountRole.getRoleId()){
            QueryWrapper<AdminAccountRole> adminAccountRoleQueryWrapper = new QueryWrapper<>();
            adminAccountRoleQueryWrapper.eq("admin_account_id", adminAccountRole.getAdminAccountId());
            adminAccountRoleQueryWrapper.eq("role_id", adminAccountRole.getRoleId());
            adminAccountRoleService.remove(adminAccountRoleQueryWrapper);
        }
        return ResultJson.success();
    }

    /**
     * 开放平台前后台 验证码登录、找回密码 校验手机号
     */
    @GetMapping(value = "/admin-account/phone-exist-check")
    public ResultJson phoneCheck(@RequestHeader(value = "appId", required = true) String appId,
                                 @RequestHeader(value = "clientType", required = false) Integer clientType,
                                 @RequestParam(value = "phone", required = true) String phone,
                                 @RequestParam(value = "developer", required = false) String developer,
                                 App app){
        //手机号校验
        if(!ValidatorUtil.isMobile(phone)){
            return ResultJson.fail("手机号格式错误");
        }
        //校验后台是否有关联账户
        if (AppTypeEnum.SYSTEM.type != app.getAppType()) {
            AccountQuery accountQuery = new AccountQuery();
            Developer developer1 = new Developer();
            accountQuery.setPhone(phone);
            if (StringUtils.isNotEmpty(developer)) {
                developer1 = developerService.getByCode(developer);
                if (null == developer1) {
                    return ResultJson.fail("开发者不存在");
                }
                if (DevelopStatusEnum.CHECKING.id == developer1.getStatus()){
                    return ResultJson.fail("开发者审核中");
                }
                accountQuery.setDevelopId(developer1.getId());
            }else{
                accountQuery.setDevelopId(app.getDevelopId());
            }
            Account account = accountService.getAccount(null, accountQuery);
            if (null == account) {
                return ResultJson.fail("帐号无效或不受支持");
            }
            return ResultJson.success(true);
        }
        QueryWrapper<AdminAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        queryWrapper.eq("develop_id",app.getDevelopId());
        queryWrapper.eq("is_deleted",0);
        try {
            AdminAccount adminAccount = adminAccountService.getOne(queryWrapper);
            if (null == adminAccount){
                return ResultJson.fail("帐号无效或不受支持");
            }
        }catch (MyBatisSystemException e){
            return ResultJson.fail("数据异常");
        }
        return ResultJson.success(true);
    }

    /**
     * 启用/禁用
     * @param adminAccount
     * @return
     */
    @PostMapping("/admin-account/update-status")
    public ResultJson updateStatus(@RequestBody AdminAccount adminAccount){
        if(null == adminAccount.getId() || null == adminAccount.getStatus()){
            return ResultJson.fail("参数错误");
        }
        AdminAccount ac = adminAccountService.getById(adminAccount.getId());
        if(null == ac){
            return ResultJson.fail("账号不存在");
        }
        ac.setStatus(adminAccount.getStatus());
        adminAccountService.updateById(ac);
        return ResultJson.success();
    }

    @RequestMapping("/admin-account/delete")
    public ResultJson delete(Integer id){
        adminAccountService.delete(id);
        return ResultJson.success();
    }

    /**
     * 运管平台帐号重置密码 （或修改密码）
     * @param appId
     * @param clientType
     * @param industryId
     * @param accountPersonalDTO
     * @return
     */
    @PostMapping(value = "/admin-account/pwd-forgot-reset")
    public ResultJson pwdForgotResetAdmin(@RequestHeader(value = "appId", required = true) String appId,
                                          @RequestHeader(value = "clientType", required = false) Integer clientType,
                                          @RequestHeader(value = "industryId", required = true) Short industryId,
                                          @RequestBody AccountPersonalDTO accountPersonalDTO, AdminAccount adminAccount){
        if (null == accountPersonalDTO.getVerifyType()) {
            log.info("缺少设置密码类型，verifyType为空");
            return ResultJson.fail("参数异常");
        }
        String newPwd = accountPersonalDTO.getNewPwd();
        Integer verifyType = accountPersonalDTO.getVerifyType();
        ResultJson resultJson = null;
        PasswordEditEnum passwordEditEnum = PasswordEditEnum.getPasswordEditEnum(verifyType);
        if (PasswordEditEnum.PHONE_VERIFY.equals(passwordEditEnum)) {
            if (StringUtils.isEmpty(accountPersonalDTO.getPhone())) {
                return ResultJson.fail("手机号不能为空");
            }
            String phone = accountPersonalDTO.getPhone();
            //手机号格式校验
            CentDataVerifyUtil.phoneVerify(phone);
            //校验当前手机号是否存在关联的账号
            QueryWrapper<AdminAccount> accountQueryWrapper = new QueryWrapper<>();
            accountQueryWrapper.eq("phone", phone);
            try {
                Integer developId = adminAccountService.getById(adminAccount.getId()).getDevelopId();
                accountQueryWrapper.eq("develop_id",developId);
            }catch (Exception e){
                e.printStackTrace();
            }
            AdminAccount one = adminAccountService.getOne(accountQueryWrapper);
            if (null == one) {
                log.info("当前手机号未关联账号,phone={},industryId={},developId={}", phone, industryId,adminAccount.getDevelopId());
                return ResultJson.fail("此账号无效或不受支持");
            }
            //校验新旧密码是否相同
            if (StringUtils.isNotEmpty(one.getLoginName()) && StringUtils.isNotEmpty(newPwd)) {
                if (one.getLoginName().equals(newPwd)) {
                    log.info("密码与用户名重复,账号id={}", one.getId());
                    return ResultJson.fail("密码格式错误");
                }
            }
            //校验短信验证码是否正确
            if (StringUtils.isEmpty(accountPersonalDTO.getMsgCode())) {
                return ResultJson.fail("短信验证码不能为空");
            }
            String msgCode = accountPersonalDTO.getMsgCode();
            //短信验证码校验
            resultJson = messageCodeService.phoneMsgCodeVerify(String.valueOf(industryId), phone, msgCode, true);
            if (!CodeEnum.SUCCESS.getCode().equals(resultJson.getCode())) {
                return resultJson;
            }
            //修改密码
            return adminAccountService.modifyPwd(one.getId(), newPwd);
        }else if (PasswordEditEnum.PWD_VERIFY.equals(passwordEditEnum)) {
            String key = industryId + "admin" + Constant.PWD_EDIT_ERROR_LOCKING + adminAccount.getId();
            Long increment = redisTemplate.opsForValue().increment(key);
            redisTemplate.expire(key,10*60 , TimeUnit.SECONDS);
            if(increment > 5){
                return ResultJson.fail(CodeEnum.LOGIN_PWD_LOCKING.getCode(), "尝试过多，请于10分钟后再尝试");
            }
            ResultJson resultJson1 = adminAccountService.verifyPwd(adminAccount.getId(), accountPersonalDTO.getPwd());
            if(!resultJson1.getState()){
                return resultJson1;
            }
            redisTemplate.delete(key);
            return adminAccountService.modifyPwd(adminAccount.getId(), newPwd);
        }else{
            return ResultJson.fail("参数错误");
        }
    }
    /**
     * 修改手机号(后台账号)
     */
    @PostMapping("/admin-account/phone-edit-verify")
    public ResultJson phoneEdit(
            AdminAccount adminAccount,
            @RequestHeader(value = "appId", required = true) String appId,
            @RequestHeader(value = "clientType", required = false) Integer clientType,
            @RequestHeader(value = "industryId", required = true) Short industryId,
            @RequestBody AccountPersonalDTO accountPersonalDTO, Developer developer) {
        adminAccount.setIndustryId(industryId);
        adminAccount.setDevelopId(developer.getId());
        return adminAccountService.modifyPhone(adminAccount, accountPersonalDTO);
    }

    /**
     * 详情
     * @return
     */
    @PostMapping("/admin-account/detail")
    public ResultJson detail(AdminAccount adminaccount){
        AdminAccount adminAccount = adminAccountService.getById(adminaccount.getId());
        adminAccount.setPassword("");
        return ResultJson.success(adminAccount);
    }
}
